package com.fingard.dsp.bank.directbank.chinapay04;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;
import com.fingard.dsp.bank.reqrespobj.single.detail.ReqPayRecDetail;
import com.fingard.io.FileHelper;
import com.fingard.net.ConnState;
import com.fingard.text.StringHelper;

import static com.fingard.dsp.bank.directbank.chinapay04.ChinaPay04Util.Util.convertResultStringToMap;

public class ChinaPay04BatPayRec extends ChinaPay04Base implements IBatPayRec {
    @Override
    public RetAtsBatPayRec d_1988_BatPay(ReqBatPayRec p_req1988) throws Exception {
        /**
         * 1.拼接文件
         * 2.组请求报文
         */
        //返回ATS的对象
        RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_req1988.reqHeader);
        try {
            String version = getBankConfig().getSetValue("version", "5.0.0", "1988");
            ActSetItem actItem = this.getBankConfig().getActSetItem(p_req1988.ownAct, "1988");
            String payDate = Format.Date8Format.format(p_req1988.getPayDateTime());

            //region 步骤1：生成批付文件
            /**
             * 基本要求：文件头+文件体
             * 文件体：标题+记录
             * 换行：\r\n
             * 分隔符：|
             * 文件名格式：DF+机构号（商户接入00000000）+商户号+yyyymmdd+批次号（当日四位有序纯数字）+I+.txt
             * 文件头：版本号（默认5.0.0）+总笔数+保留域1+保留域2
             * 文件体：商户代码（机构接入必填）+商户订单号（必填）+交易币种（境外交易必填，默认156）+交易金额（必填）+账号类型（必填，01-银行卡、02-存折、04-对公账户）+账号（必填）+姓名（可选）+产品类型（可选，000000-默认取值、000401-代付）+证件类型（可选）+证件号码（可选）+手机号（可选）+开户行名称（可选）+开户行省（可选）+开户行市（可选）+账单类型（可选）+附言（可选）+资金来源（可选）+付款方账号（可选）+付款方姓名（可选）+请求方保留域1（可选）+请求方保留域2（可选）+单位结算卡完整账户名称（账号类型为对公时必填）+营业执照注册号（账号类型为对公时必填）
             */
            int index = 1;
            String tmpBatchNo = "";
            String tmpBatFilePatch = "";
            //region  获取批次号 根据当日文件夹数按序往上累加，使用同步代码块防止并发
            synchronized (this) {
                String dirPath = FGBiz.dspCenter.dspSet.dataDirPath + File.separator + "tempfile" + File.separator + "ChinaPay04" + File.separator + "DF" + File.separator + actItem.appId + File.separator + actItem.merchantId + File.separator + payDate;
                File tmpFile = new File(dirPath);
                if (!tmpFile.exists()) {
                    tmpFile.mkdirs();
                } else {
                    index = tmpFile.listFiles().length + 1;
                }
                tmpBatchNo = StringHelper.padLeft(String.valueOf(index), 4, '0');
                tmpBatFilePatch = dirPath + File.separator + p_req1988.reqBatchNO + "-" + tmpBatchNo;
                File reqDirc = new File(tmpBatFilePatch);
                reqDirc.mkdir();
            }
            //endregion

            //region 组装文件内容
            String fileName = "DF" + actItem.appId + actItem.merchantId + payDate + tmpBatchNo + "I.txt";
            String contentHead = version + FILEFIELDUNION + StringHelper.amountMultiply100(p_req1988.totalAmt) + FILEFIELDUNION + p_req1988.totalNum + FILEFIELDUNION + "" + FILEFIELDUNION + "" + FILELINEUNION;
            String contentBodyTitle = "商户代码" + FILEFIELDUNION + "商户订单号" + FILEFIELDUNION + "交易币种" + FILEFIELDUNION + "交易金额" + FILEFIELDUNION + "账号类型" + FILEFIELDUNION + "账号" + FILEFIELDUNION + "姓名" + FILEFIELDUNION + "单位结算卡完整账户名称" + FILEFIELDUNION + "营业执照注册号" + FILELINEUNION;//"orderId" + FILEFIELDUNION + "currencyCode" + FILEFIELDUNION + "txnAmt" + FILEFIELDUNION + "accType" + FILEFIELDUNION + "accNo" + FILEFIELDUNION + "customerNm" + FILEFIELDUNION + "comDebitCardAccName" + FILEFIELDUNION + "businessLicenseRegNo" + FILELINEUNION_BODY;
            StringBuilder contentBody = new StringBuilder();
            while (p_req1988.readRecord()) {
                ReqPayRecDetail tmpDetail = p_req1988.readedDetail;
                String code = actItem.termId;
                contentBody.append(code);
                contentBody.append(FILEFIELDUNION);
                String order = tmpDetail.askNumber;
                contentBody.append(order);
                contentBody.append(FILEFIELDUNION);
                String cur = convertCurToBank(tmpDetail.payCur);
                contentBody.append(cur);
                contentBody.append(FILEFIELDUNION);
                String amout = StringHelper.amountMultiply100(tmpDetail.payAmount);
                contentBody.append(amout);
                contentBody.append(FILEFIELDUNION);
                String actType = "1".equals(tmpDetail.isPrivate) ? "01" : "04";
                contentBody.append(actType);
                contentBody.append(FILEFIELDUNION);
                String actNum = tmpDetail.recAct;
                contentBody.append(actNum);
                contentBody.append(FILEFIELDUNION);
                String actName = tmpDetail.recName;
                contentBody.append(actName);
                contentBody.append(FILEFIELDUNION);
                String actFullName = "";
                String actCode = "";
                if ("2".equals(tmpDetail.isPrivate)) {
                    String info = getBankConfig().getMapValueByKey("pubBatPayRecInfo", actNum);
                    if (info.contains("@@")) {
                        String[] infos = info.split("@@");
                        actFullName = infos[0];
                        actCode = infos[1];
                    }
                }
                contentBody.append(actFullName);
                contentBody.append(FILEFIELDUNION);
                contentBody.append(actCode);
                contentBody.append(FILELINEUNION_BODY);
            }
            String filePath = tmpBatFilePatch + File.separator + fileName;
            String fileContent = contentHead + contentBodyTitle + contentBody.toString();//"5.0.0|30000|1||\r\norderId|currencyCode|txnAmt|accType|accNo|customerNm|bizType|certifTp|certifId|phoneNo|postscript\r\n0823000300003371|156|30000|01|6212261202002704030| 张三|000401|01|33012119700212971X|18606560040| 样例展示";
            FileHelper.writeFile(filePath, fileContent, getCharset());
            WriteBankLogLn("已生成批付文件，路径位于：" + filePath);
            //endregion
            //endregion

            //region 步骤2：发起批付提交
            /**
             * 请求报文参数
             */
            Map<String, String> data = new HashMap<String, String>();
            /***银联全渠道系统，产品参数，除了encoding自行选择外其他不需修改***/
            data.put("version", version);           //版本号
            data.put("encoding", getCharset());         //字符集编码 可以使用UTF-8,GBK两种方式
            data.put("signMethod", "01"); //签名方法
            data.put("txnType", "21");       //取值：21 批量交易
            data.put("txnSubType", "03");           //填写：01：退货02：代收03：代付
            data.put("bizType", "000401");   //代付 000401
            data.put("channelType", "07");          //渠道类型
            /***商户接入参数***/
            data.put("accessType", "0");       //接入类型，商户接入填0 ，不需修改（0：直连商户 2：平台商户）
            data.put("merId", actItem.merchantId);       //商户号码，请改成自己申请的商户号，【测试777开通的商户号不支持代收产品】
            /**与批量文件内容相关的参数**/
            data.put("batchNo", tmpBatchNo);            //批量交易时填写，当天唯一,0001-9999，商户号+批次号+上交易时间确定一笔交易
            data.put("txnTime", Format.DateTime14Format.format(p_req1988.getPayDateTime()));  //前8位需与文件中的委托日期保持一致
            data.put("totalQty", p_req1988.totalNum);             //批量交易时填写，填写批量文件中总的交易比数
            data.put("totalAmt", StringHelper.amountMultiply100(p_req1988.totalAmt));           //批量交易时填写，填写批量文件中总的交易金额
            //使用DEFLATE压缩算法压缩后，Base64编码的方式传输经压缩编码的文件内容，文件中的商户号必须与merId一致
            data.put("fileContent", enCodeFileContent(filePath, getCharset()));
            /**对请求参数进行签名并发送http post请求，接收同步应答报文**/

            /**请求参数设置完毕，以下对请求参数进行签名并发送http post请求，接收同步应答报文------------->**/

            StringBuilder errorSb = new StringBuilder();
            data = signWithFilterBlank(p_req1988.ownAct, data, errorSb);
            String errorInfo = errorSb.toString();
            if (StringHelper.isNullOrEmpty(errorInfo)) {
                String[] tmpStrRet = sendToBank(data, bankFront.getUrl("1988"));
                if (tmpStrRet[0].length() == 0) {
                    Map<String, String> rspData = convertResultStringToMap(tmpStrRet[1]);
                    if (!rspData.isEmpty()) {
                        WriteBankLogLn("验证签名成功");
                        if (validate(p_req1988.ownAct, rspData, errorSb)) {
                            String respCode = rspData.get("respCode");
                            String respMsg = rspData.get("respMsg");
                            retAts.respCode = "0";
                            retAts.respInfo = respMsg;
                            retAts.reqSeqID = p_req1988.reqBatchNO;
                            retAts.transState = respCode;
                            retAts.payInfoCode = respCode;
                        } else {
                            retAts.respCode = "-1";
                            retAts.respInfo = errorSb.toString();
                        }
                    }
                } else if (tmpStrRet[0].equals(ConnState.FAIL) || tmpStrRet[0].equals(FailCode.E9981)) {
                    retAts.respCode = "0";
                    retAts.respInfo = tmpStrRet[1];
                    retAts.reqSeqID = p_req1988.reqBatchNO;
                    retAts.transState = PaymentState.FAIL_Batch;
                    retAts.payInfoCode = tmpStrRet[0];
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = tmpStrRet[1];
                }

            } else {
                retAts.respCode = "0";
                retAts.respInfo = errorInfo;
                retAts.reqSeqID = p_req1988.reqBatchNO;
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = PaymentState.FAIL_Batch;
            }
            //endregion

        } catch (Exception e) {
            retAts.respCode = "-1";
            retAts.respInfo = e.toString();
            e.printStackTrace();
        }
        if (retAts.respCode.equals("-1") && StringHelper.isNullOrEmpty(retAts.reqSeqID)) {
            retAts.reqSeqID = p_req1988.reqBatchNO;
        }
        retAts.writeRetToATS();
        return retAts;
    }

    @Override
    public RetAtsQryBatPayRec d_1998_QryBatPay(ReqQryBatPayRec p_req1998) throws Exception {
        //返回ATS的对象
        RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_req1998.reqHeader);
        try {
            ActSetItem actItem = this.getBankConfig().getActSetItem(p_req1998.ownAct, "1988");
            String payDate = Format.Date8Format.format(p_req1998.getBgnDateTime());
            //根据ats批次号获取提交银行的批次号
            String dirPath = FGBiz.dspCenter.dspSet.dataDirPath + File.separator + "tempfile" + File.separator + "ChinaPay04" + File.separator + "DF" + File.separator + actItem.appId + File.separator + actItem.merchantId + File.separator + payDate;
            boolean hasMatched = false;
            String tmpBatchNo = "";
            String matchFlag = p_req1998.reqBatchNO + "-";
            File dir = new File(dirPath);
            if (dir.exists()) {
                File[] tmpFiles = dir.listFiles();
                for (File file : tmpFiles) {
                    if (file.getName().contains(matchFlag)) {
                        hasMatched = true;
                        tmpBatchNo = file.getName().replace(matchFlag, "");
                    }
                }
            }
            if (hasMatched) {
                String version = getBankConfig().getSetValue("version", "5.0.0", "1998");
                Map<String, String> data = new HashMap<String, String>();
                /***银联全渠道系统，产品参数，除了encoding自行选择外其他不需修改***/
                data.put("version", version);            //版本号
                data.put("encoding", getCharset());      //字符集编码 可以使用UTF-8,GBK两种方式
                data.put("signMethod", "01"); //签名方法
                data.put("txnType", "22"); //交易类型 22 批量查询
                data.put("txnSubType", "03");//交易子类 03 代付
                data.put("bizType", "000401"); //代付 000401
                data.put("channelType", "07"); //渠道类型
                /***商户接入参数***/
                data.put("accessType", "0"); //接入类型，商户接入填0 ，不需修改（0：直连商户 2：平台商户）
                data.put("merId", actItem.merchantId);//商户号码，请改成自己申请的商户号，【测试777开通的商户号不支持代收产品】
                /**与批量查询相关的参数**/
                data.put("batchNo", tmpBatchNo);  //被查询批量交易批次号
                data.put("txnTime", Format.DateTime14Format.format(p_req1998.getBgnDateTime()));//原批量代收请求的交易时间
                /**对请求参数进行签名并发送http post请求，接收同步应答报文**/
                StringBuilder errorSb = new StringBuilder();
                data = signWithFilterBlank(p_req1998.ownAct, data, errorSb);
                String errorInfo = errorSb.toString();
                if (StringHelper.isNullOrEmpty(errorInfo)) {
                    String[] tmpStrRet = sendToBank(data, bankFront.getUrl("1998"));
                    if (tmpStrRet[0].length() == 0) {
                        Map<String, String> rspData = convertResultStringToMap(tmpStrRet[1]);
                        if (!rspData.isEmpty()) {
                            if (validate(p_req1998.ownAct, rspData, errorSb)) {
                                if (("00").equals(rspData.get("respCode"))) {
                                    //成功
                                    //落地查询结果样例
                                    String fileContent = rspData.get("fileContent");
                                    String queryResult = getFileContent(fileContent, getCharset());
                                    String[] resultContent = queryResult.split(FILELINEUNION);
                                    int resultLength = resultContent.length;
                                    if (resultLength > 1) {
                                        retAts.respCode = "0";
                                        retAts.writeBeforeDetail();
                                        RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();
                                        for (int i = 2; i < resultLength; i++) {
                                            String[] resultInfo = resultContent[i].split(FILEFIELDUNION);
                                            tmpRetDetail.result = resultInfo[0];
                                            tmpRetDetail.memo = resultInfo[1];
                                            tmpRetDetail.payInfoCode = resultInfo[0];
                                            tmpRetDetail.postScript = resultInfo[9];
                                            tmpRetDetail.recAct = resultInfo[11];
                                            tmpRetDetail.payAmount = StringHelper.amountDivide100(resultInfo[13]);
                                            tmpRetDetail.recName = resultInfo[15];
                                            retAts.writeRetDetail(tmpRetDetail);
                                        }
                                    } else {
                                        String rejectContent = resultContent[0];
                                        String[] resultInfo = rejectContent.split(FILEFIELDUNION);
                                        retAts.respCode = "0";
                                        retAts.respInfo = resultInfo.length > 1 ? resultInfo[1] : "";
                                        retAts.reqSeqID = p_req1998.reqBatchNO;
                                        retAts.payInfoCode = resultInfo[0];
                                        retAts.transState = resultInfo[0];
                                        retAts.writeBeforeDetail();
                                    }
                                } else if (("34").equals(rspData.get("respCode")) && ("批次（" + tmpBatchNo + "）不存在[7103401]").equals(rspData.get("respMsg"))) {
                                    retAts.respCode = "0";
                                    retAts.respInfo = "记录不存在";
                                    retAts.reqSeqID = p_req1998.reqBatchNO;
                                    retAts.payInfoCode = PaymentState.FAIL_Batch;
                                    retAts.transState = PaymentState.FAIL_Batch;
                                    retAts.writeBeforeDetail();

                                } else {
                                    retAts.respCode = "-1";
                                    retAts.respInfo = rspData.get("respMsg");
                                }
                            } else {
                                retAts.respCode = "-1";
                                retAts.respInfo = errorSb.toString();

                            }
                        } else {
                            retAts.respCode = "-1";
                            retAts.respInfo = "未能正常接受到响应！";
                        }

                    } else {
                        retAts.respCode = "-1";
                        retAts.respInfo = tmpStrRet[1];
                    }

                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = errorInfo;
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = "根据当前批次号未能获取到提交银联的批次号，请核查！";
            }

        } catch (Exception e) {
            retAts.respCode = "-1";
            retAts.respInfo = e.getMessage();
            e.printStackTrace();
        }
        if (retAts.respCode.equals("-1") && StringHelper.isNullOrEmpty(retAts.reqSeqID)) {
            retAts.reqSeqID = p_req1998.reqBatchNO;
        }
        if (retAts.respCode.equals("-1")) {
            retAts.writeBeforeDetail();
        }
        retAts.writeAfterDetail();
        return retAts;
    }

    @Override
    public RetAtsBatPayRec d_9188_BatPay(ReqBatPayRec p_req9188) throws Exception {
        return null;
    }

    @Override
    public RetAtsQryBatPayRec d_9198_QryBatPay(ReqQryBatPayRec p_req9198) throws Exception {
        return null;
    }
}
